/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2008，所有权利保留。
 * 
 * 项目名：	rumba
 * 文件名：	StaticServlet.java
 * 模块说明：	
 * 修改历史：
 * Jan 2, 2008 - lxm - 创建。
 */
package com.hd123.rumba.request;

import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

/**
 * 设计用于访问静态资源的Servlet。
 * <p>
 * 
 * 引入此类的主要原因，是用于解决gwt技术引入后，如何访问gwt模块外的一些静态资源的问题。需要说明的是，这里所说的静态资源目前特指物理上位于<code>{$WebRoot}\static</code>中的所有资源。
 * <p>
 * 
 * 使用前首先需要修改web.xml配置。以下是gwt Host下的典型配置：
 * 
 * <pre><code>
 * &lt;servlet&gt;
 * &nbsp; &lt;servlet-name&gt;static&lt;/servlet-name&gt;
 * &nbsp; &lt;servlet-class&gt;com.hd123.rumba.request.StaticServlet&lt;/servlet-class&gt;
 * &nbsp; &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
 * &lt;/servlet&gt;
 *     
 * &lt;servlet-mapping&gt;
 * &nbsp; &lt;servlet-name&gt;static&lt;/servlet-name&gt;
 * &nbsp; &lt;url-pattern&gt;/static/*&lt;/url-pattern&gt;
 * &lt;/servlet-mapping&gt;
 * </code></pre>
 * 
 * 对于部属模式，则需要根据根据实际的部属情况修改<code>servlet-mapping|url-pattern</code>的内容，一种常见的写法是“<code>/www/static/*</code>”，具体取决于部属程序的写法。
 * <p>
 * 
 * 配置完成后对于程序中需要访问静态资源的地方，只须确保访问路径与web.xml的配置保持一致。以下是html文件的一个典型写法：
 * 
 * <pre><code>
 * &lt;script type=&quot;text/javascript&quot; src=&quot;../static/rumba/js-ext/ext-all.js&quot;&gt;&lt;/script&gt;
 * </code></pre>
 * 
 * 还可以通过程序动态访问静态资源，参见{@link com.hd123.rumba.gwt.base.client.util.GWTUtil#getStaticContentURL}。
 * <p>
 * 
 * @author lxm
 * 
 */
public class StaticServlet extends HttpServlet {

  private static final Logger logger = Logger.getLogger(StaticServlet.class);

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {
    try {
      serveResource(request, response);
    } catch (IOException ex) {
      // we probably have this check somewhere else too.
      if (ex.getMessage() != null && ex.getMessage().indexOf("Broken pipe") >= 0) {
        // ignore it.
      }
      throw ex;
    }
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {
    doGet(request, response);
  }

  private String getRelativePath(HttpServletRequest request) {
    // String result = request.getServletPath() + request.getPathInfo();
    String result = "/static" + request.getPathInfo();
    if ((result == null) || (result.equals(""))) {
      result = "/";
    }
    return (result);
  }

  private void serveResource(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {
    String path = getRelativePath(request);
    logger.debug("StaticServlet: " + path);

    path = this.getServletContext().getRealPath(path);
    response.setContentType(this.getServletContext().getMimeType(path));
    ServletOutputStream out = response.getOutputStream();
    try {
      FileInputStream in = new FileInputStream(path);
      byte abyte0[] = new byte[2048];
      int bytesRead, len = 0;
      while (-1 != (bytesRead = in.read(abyte0, 0, abyte0.length))) {
        len += bytesRead;
        out.write(abyte0, 0, bytesRead);
      }
      response.setContentLength(len);
    } finally {
      out.flush();
    }
  }

}
